package cn.sc.summer.gateway.listener;

import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.rabbitmq.client.Channel;
import cn.sc.summer.constant.gateway.GatewayConstant;
import cn.sc.summer.constant.gateway.GatewayInstance;
import cn.sc.summer.constant.rabbit.RabbitConstant;
import cn.sc.summer.gateway.util.WarmUpUtil;
import cn.sc.summer.rabbitmq.po.RabbitMessage;
import cn.sc.summer.rabbitmq.service.RabbitConsumerService;
import cn.sc.summer.rabbitmq.util.RabbitUtil;
import cn.sc.summer.redis.util.RedisHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cache.Cache;
import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheManager;
import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 类名：openfeign调用网关实例刷新
 *
 * @author a-xin
 * @date 2024/8/3 01:09
 */
@Slf4j
@Component
public class FeignInstanceRefresh extends RabbitConsumerService {

    @Resource
    private ApplicationContext applicationContext;

    @Override
    @RabbitListener(queues = RabbitConstant.GATEWAY_INSTANCE_QUEUE_FEIGN, ackMode = "MANUAL")
    public void consumer(String jsonStr, Message message, Channel channel) {
        try {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            RabbitMessage<GatewayInstance> gatewayInstanceRabbitMessage = RabbitUtil.checkMessage(jsonStr, new TypeReference<GatewayInstance>() {
            });
            GatewayInstance gatewayInstance = gatewayInstanceRabbitMessage.getMessage();
            if (ObjectUtil.isNotNull(gatewayInstance)) {
                log.warn("==> RabbitMq refresh gateway instance: {}", gatewayInstance);
                if (RedisHelper.hasKey(GatewayConstant.SERVER_INSTANCE_KEY + ":" + gatewayInstance.getServerKey())) {
                    ObjectProvider<LoadBalancerCacheManager> cacheManagerProvider = applicationContext.getBeanProvider(LoadBalancerCacheManager.class);
                    Cache cache = cacheManagerProvider.getIfAvailable().getCache(CachingServiceInstanceListSupplier.SERVICE_INSTANCE_CACHE_NAME);
                    if (cache != null) {
                        boolean present = cache.evictIfPresent(gatewayInstance.getServerName());
                        log.info("==> SpringCloud Gateway: The microservice {}[{}] instance is refreshed!", gatewayInstance.getServerName(), present);
                    }
                    String body = WarmUpUtil.warmUp(gatewayInstance.getServerHost());
                    log.warn("==> The {} instance warm up result: {}", gatewayInstance.getServerName(), body);
                }
            } else {
                log.error("==> The refresh instance is null!");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
